From 5186f83702fe010757ceda79b59483d9b4d0b4f3 Mon Sep 17 00:00:00 2001 From: "iap10@tetris.cl.cam.ac.uk" Date: Sun, 21 Mar 2004 19:14:29 +0000 Subject: [PATCH] bitkeeper revision 1.794.1.3 (405de995_4scoWE5EfQzN5TSoyS8Gw) fixes plus new performance counters --- xen/arch/i386/process.c | 2 +- xen/arch/i386/traps.c | 4 -- xen/common/memory.c | 42 ++++++++++++----- xen/common/perfc.c | 43 ++++++++++++++++- xen/common/shadow.c | 89 +++++++++++++++++++++++++++++------ xen/include/xeno/perfc.h | 12 +++++ xen/include/xeno/perfc_defn.h | 4 +- xen/include/xeno/shadow.h | 7 ++- 8 files changed, 167 insertions(+), 36 deletions(-) diff --git a/xen/arch/i386/process.c b/xen/arch/i386/process.c index 8ed1cf2dc2..2c53801089 100644 --- a/xen/arch/i386/process.c +++ b/xen/arch/i386/process.c @@ -290,8 +290,8 @@ void switch_to(struct task_struct *prev_p, struct task_struct *next_p) if( next_p->mm.shadowmode ) { - write_cr3_counted(pagetable_val(next_p->mm.shadowtable)); check_pagetable( next_p->mm.pagetable, "switch" ); + write_cr3_counted(pagetable_val(next_p->mm.shadowtable)); } else #endif diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c index 717ca6d2cb..eed1fb9faf 100644 --- a/xen/arch/i386/traps.c +++ b/xen/arch/i386/traps.c @@ -340,15 +340,11 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) } #ifdef CONFIG_SHADOW -//printk("1"); -check_pagetable( current->mm.pagetable, "pre-sf" ); if ( p->mm.shadowmode && addr < PAGE_OFFSET && shadow_fault( addr, error_code ) ) { - check_pagetable( current->mm.pagetable, "post-sfa" ); return; // return true if fault was handled } - check_pagetable( current->mm.pagetable, "post-sfb" ); #endif if ( unlikely(!(regs->xcs & 3)) ) diff --git a/xen/common/memory.c b/xen/common/memory.c index e672f78fe0..f6e8155f71 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -764,19 +764,26 @@ void free_page_type(struct pfn_info *page, unsigned int type) switch ( type ) { case PGT_l1_page_table: - return free_l1_table(page); - case PGT_l2_page_table: - return free_l2_table(page); - default: - BUG(); - } + free_l1_table(page); +#ifdef CONFIG_SHADOW + // assume we're in shadow mode if PSH_shadowed set + if ( current->mm.shadowmode && page->shadow_and_flags & PSH_shadowed ) + unshadow_table( page-frame_table, type ); +#endif + return; + case PGT_l2_page_table: + free_l2_table(page); #ifdef CONFIG_SHADOW - // assume we're in shadow mode if PSH_shadowed set - if ( page->shadow_and_flags & PSH_shadowed ) - unshadow_table( page-frame_table ); + // assume we're in shadow mode if PSH_shadowed set + if ( current->mm.shadowmode && page->shadow_and_flags & PSH_shadowed ) + unshadow_table( page-frame_table, type ); #endif + return; + default: + BUG(); + } } @@ -846,7 +853,17 @@ static int do_extended_command(unsigned long ptr, unsigned long val) shadow_mk_pagetable(pfn << PAGE_SHIFT, current->mm.shadowmode); #endif invalidate_shadow_ldt(); - percpu_info[cpu].deferred_ops |= DOP_FLUSH_TLB; + + percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB; +#ifdef CONFIG_SHADOW + if ( unlikely(current->mm.shadowmode) ) + { + check_pagetable( current->mm.pagetable, "pre-stlb-flush" ); + write_cr3_counted(pagetable_val(current->mm.shadowtable)); + } + else +#endif + write_cr3_counted(pagetable_val(current->mm.pagetable)); } else { @@ -1082,7 +1099,10 @@ check_pagetable( current->mm.pagetable, "mmu" ); // XXX XXX XXX XXX XXX { #ifdef CONFIG_SHADOW if ( unlikely(current->mm.shadowmode) ) - write_cr3_counted(pagetable_val(current->mm.shadowtable)); + { + check_pagetable( current->mm.pagetable, "pre-stlb-flush" ); + write_cr3_counted(pagetable_val(current->mm.shadowtable)); + } else #endif write_cr3_counted(pagetable_val(current->mm.pagetable)); diff --git a/xen/common/perfc.c b/xen/common/perfc.c index 00d0505503..af9abbb67c 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -8,12 +8,20 @@ #undef PERFCOUNTER #undef PERFCOUNTER_CPU #undef PERFCOUNTER_ARRAY +#undef PERFSTATUS +#undef PERFSTATUS_CPU +#undef PERFSTATUS_ARRAY #define PERFCOUNTER( var, name ) { name, TYPE_SINGLE, 0 }, #define PERFCOUNTER_CPU( var, name ) { name, TYPE_CPU, 0 }, #define PERFCOUNTER_ARRAY( var, name, size ) { name, TYPE_ARRAY, size }, +#define PERFSTATUS( var, name ) { name, TYPE_S_SINGLE, 0 }, +#define PERFSTATUS_CPU( var, name ) { name, TYPE_S_CPU, 0 }, +#define PERFSTATUS_ARRAY( var, name, size ) { name, TYPE_S_ARRAY, size }, static struct { char *name; - enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY } type; + enum { TYPE_SINGLE, TYPE_CPU, TYPE_ARRAY, + TYPE_S_SINGLE, TYPE_S_CPU, TYPE_S_ARRAY + } type; int nr_elements; } perfc_info[] = { #include @@ -38,10 +46,12 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs) switch ( perfc_info[i].type ) { case TYPE_SINGLE: + case TYPE_S_SINGLE: printk("TOTAL[%10d]", atomic_read(&counters[0])); counters += 1; break; case TYPE_CPU: + case TYPE_S_CPU: for ( j = sum = 0; j < smp_num_cpus; j++ ) sum += atomic_read(&counters[j]); printk("TOTAL[%10d] ", sum); @@ -50,6 +60,7 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs) counters += NR_CPUS; break; case TYPE_ARRAY: + case TYPE_S_ARRAY: for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ ) sum += atomic_read(&counters[j]); printk("TOTAL[%10d] ", sum); @@ -64,9 +75,37 @@ void perfc_printall(u_char key, void *dev_id, struct pt_regs *regs) void perfc_reset(u_char key, void *dev_id, struct pt_regs *regs) { + int i, j, sum; s_time_t now = NOW(); + atomic_t *counters = (atomic_t *)&perfcounters; + printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", (u32)(now>>32), (u32)now); - memset(&perfcounters, 0, sizeof(perfcounters)); + + // leave STATUS counters alone -- don't reset + + for ( i = 0; i < NR_PERFCTRS; i++ ) + { + switch ( perfc_info[i].type ) + { + case TYPE_SINGLE: + atomic_set(&counters[0],0); + case TYPE_S_SINGLE: + counters += 1; + break; + case TYPE_CPU: + for ( j = sum = 0; j < smp_num_cpus; j++ ) + atomic_set(&counters[j],0); + case TYPE_S_CPU: + counters += NR_CPUS; + break; + case TYPE_ARRAY: + for ( j = sum = 0; j < perfc_info[i].nr_elements; j++ ) + atomic_set(&counters[j],0); + case TYPE_S_ARRAY: + counters += j; + break; + } + } } diff --git a/xen/common/shadow.c b/xen/common/shadow.c index f43968018f..a0df57d8f1 100644 --- a/xen/common/shadow.c +++ b/xen/common/shadow.c @@ -10,7 +10,7 @@ #ifdef CONFIG_SHADOW -#if 1 +#if SHADOW_DEBUG #define MEM_VLOG(_f, _a...) \ printk("DOM%llu: (file=shadow.c, line=%d) " _f "\n", \ current->domain , __LINE__ , ## _a ) @@ -63,11 +63,14 @@ pagetable_t shadow_mk_pagetable( unsigned long gptbase, return mk_pagetable(spfn << PAGE_SHIFT); } -void unshadow_table( unsigned long gpfn ) +void unshadow_table( unsigned long gpfn, unsigned int type ) { unsigned long spfn; -MEM_VLOG("unshadow_table %08lx\n", gpfn ); + MEM_VLOG("unshadow_table type=%08x gpfn=%08lx, spfn=%08lx", + type, + gpfn, + frame_table[gpfn].shadow_and_flags & PSH_pfn_mask ); perfc_incrc(unshadow_table_count); @@ -80,8 +83,8 @@ MEM_VLOG("unshadow_table %08lx\n", gpfn ); frame_table[gpfn].shadow_and_flags=0; frame_table[spfn].shadow_and_flags=0; -#ifdef DEBUG - { // XXX delete me! +#if 0 // XXX leave as might be useful for later debugging + { int i; unsigned long * spl1e = map_domain_mem( spfn<mm.pagetable, "pre-sf" ); + if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) ) { MEM_VVLOG("shadow_fault - EXIT: read gpte faulted" ); @@ -250,7 +270,7 @@ int shadow_fault( unsigned long va, long error_code ) unsigned long gpde, spde, gl1pfn, sl1pfn; MEM_VVLOG("3: not shadowed or l2 insufficient gpte=%08lx spte=%08lx",gpte,spte ); - + gpde = l2_pgentry_val(linear_l2_table[va>>L2_PAGETABLE_SHIFT]); gl1pfn = gpde>>PAGE_SHIFT; @@ -266,6 +286,7 @@ int shadow_fault( unsigned long va, long error_code ) MEM_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn); perfc_incrc(shadow_l1_table_count); + perfc_incr(shadow_l1_pages); sl1pfn_info->shadow_and_flags = PSH_shadow | gl1pfn; frame_table[gl1pfn].shadow_and_flags = PSH_shadowed | sl1pfn; @@ -337,6 +358,8 @@ int shadow_fault( unsigned long va, long error_code ) perfc_incrc(shadow_fixup_count); + check_pagetable( current->mm.pagetable, "post-sf" ); + return 1; // let's try the faulting instruction again... } @@ -521,9 +544,11 @@ int check_l1_table( unsigned long va, unsigned long g2, unsigned long s2 ) int j; unsigned long *gpl1e, *spl1e; - gpl1e = (unsigned long *) &(linear_pg_table[ va>>PAGE_SHIFT]); - spl1e = (unsigned long *) &(shadow_linear_pg_table[ va>>PAGE_SHIFT]); + //gpl1e = (unsigned long *) &(linear_pg_table[ va>>PAGE_SHIFT]); + //spl1e = (unsigned long *) &(shadow_linear_pg_table[ va>>PAGE_SHIFT]); + gpl1e = map_domain_mem( g2<>(L2_PAGETABLE_SHIFT))-DOMAIN_ENTRIES_PER_L2_PAGETABLE) + * sizeof(l2_pgentry_t)) ) + { + printk("gpfn=%08lx spfn=%08lx\n", gpfn, spfn); + for (i=DOMAIN_ENTRIES_PER_L2_PAGETABLE; + i<(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT)); + i++ ) + printk("+++ (%d) %08lx %08lx\n",i, + l2_pgentry_val(gpl2e[i]), l2_pgentry_val(spl2e[i]) ); + FAILPT("hypervisor entries inconsistent"); + } + + if ( (l2_pgentry_val(spl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != + l2_pgentry_val(gpl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT])) ) + FAILPT("hypervisor linear map inconsistent"); + + if ( (l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]) != + ((spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR)) ) + FAILPT("hypervisor shadow linear map inconsistent %08lx %08lx", + l2_pgentry_val(spl2e[SH_LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT]), + (spfn << PAGE_SHIFT) | __PAGE_HYPERVISOR + ); + + if ( (l2_pgentry_val(spl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT]) != + ((__pa(frame_table[gpfn].u.domain->mm.perdomain_pt) | __PAGE_HYPERVISOR))) ) + FAILPT("hypervisor per-domain map inconsistent"); - // use the linear map to get a pointer to the L2 - gpl2e = (l2_pgentry_t *) &(linear_l2_table[0]); - spl2e = (l2_pgentry_t *) &(shadow_linear_l2_table[0]); // check the whole L2 for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) @@ -601,6 +658,8 @@ return 1; } + unmap_domain_mem( spl2e ); + unmap_domain_mem( gpl2e ); MEM_VVLOG("PT verified : l2_present = %d, l1_present = %d\n", sh_l2_present, sh_l1_present ); diff --git a/xen/include/xeno/perfc.h b/xen/include/xeno/perfc.h index 9ea244b3b8..abb36c7b1e 100644 --- a/xen/include/xeno/perfc.h +++ b/xen/include/xeno/perfc.h @@ -11,6 +11,11 @@ * PERFCOUNTER_CPU (counter, string, size) define a counter per CPU * PERFCOUNTER_ARRY (counter, string, size) define an array of counters * + * unlike "COUNTERS", "STATUS" variables DO NOT RESET + * PERFSTATUS (counter, string) define a new performance stauts + * PERFSTATUS_CPU (counter, string, size) define a status var per CPU + * PERFSTATUS_ARRY (counter, string, size) define an array of status vars + * * unsigned long perfc_value (counter) get value of a counter * unsigned long perfc_valuec (counter) get value of a per CPU counter * unsigned long perfc_valuea (counter, index) get value of an array counter @@ -32,6 +37,12 @@ atomic_t var[NR_CPUS]; #define PERFCOUNTER_ARRAY( var, name, size ) \ atomic_t var[size]; +#define PERFSTATUS( var, name ) \ + atomic_t var[1]; +#define PERFSTATUS_CPU( var, name ) \ + atomic_t var[NR_CPUS]; +#define PERFSTATUS_ARRAY( var, name, size ) \ + atomic_t var[size]; struct perfcounter_t { @@ -47,6 +58,7 @@ extern struct perfcounter_t perfcounters; #define perfc_setc(x,v) atomic_set(&perfcounters.x[smp_processor_id()], v) #define perfc_seta(x,y,v) atomic_set(&perfcounters.x[y], v) #define perfc_incr(x) atomic_inc(&perfcounters.x[0]) +#define perfc_decr(x) atomic_dec(&perfcounters.x[0]) #define perfc_incrc(x) atomic_inc(&perfcounters.x[smp_processor_id()]) #define perfc_incra(x,y) atomic_inc(&perfcounters.x[y]) #define perfc_add(x,y) atomic_add((y), &perfcounters.x[0]) diff --git a/xen/include/xeno/perfc_defn.h b/xen/include/xeno/perfc_defn.h index 0475b6371e..bf06719e35 100644 --- a/xen/include/xeno/perfc_defn.h +++ b/xen/include/xeno/perfc_defn.h @@ -30,4 +30,6 @@ PERFCOUNTER_CPU( unshadow_table_count, "unshadow_table count" ) PERFCOUNTER_CPU( shadow_fixup_count, "shadow_fixup count" ) PERFCOUNTER_CPU( shadow_update_va_fail, "shadow_update_va_fail" ) - +/* STATUS counters do not reset when 'P' is hit */ +PERFSTATUS( shadow_l2_pages, "current # shadow L2 pages" ) +PERFSTATUS( shadow_l1_pages, "current # shadow L1 pages" ) diff --git a/xen/include/xeno/shadow.h b/xen/include/xeno/shadow.h index dca0126784..7034081b48 100644 --- a/xen/include/xeno/shadow.h +++ b/xen/include/xeno/shadow.h @@ -25,7 +25,7 @@ #define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT)))) extern pagetable_t shadow_mk_pagetable( unsigned long gptbase, unsigned int shadowmode ); -extern void unshadow_table( unsigned long gpfn ); +extern void unshadow_table( unsigned long gpfn, unsigned int type ); extern unsigned long shadow_l2_table( unsigned long gpfn ); extern int shadow_fault( unsigned long va, long error_code ); extern void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte, @@ -37,6 +37,8 @@ extern void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte ); #define SHADOW_DEBUG 0 #define SHADOW_OPTIMISE 1 +#endif // end of CONFIG_SHADOW + #if SHADOW_DEBUG extern int check_pagetable( pagetable_t pt, char *s ); #else @@ -44,5 +46,6 @@ extern int check_pagetable( pagetable_t pt, char *s ); #endif -#endif + + #endif -- 2.30.2